package org.seven.jrdp.commons.mybatis.plugin;

import java.lang.reflect.Field;
import java.util.Properties;

import javax.persistence.Column;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.seven.jrdp.commons.constant.GlobalContants;
import org.seven.jrdp.commons.util.DateTimeUtils;
import org.seven.jrdp.commons.util.ShiroUtils;
import org.seven.jrdp.commons.util.StringUtils;

@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class AuditPlugin implements Interceptor {
	public Object intercept(Invocation invocation) throws Throwable {
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
		Object parameter = invocation.getArgs()[1];
		if (parameter == null) {
			return invocation.proceed();
		}
		Field[] fields = parameter.getClass().getDeclaredFields();
		if (SqlCommandType.INSERT == sqlCommandType) {
			for (Field field : fields) {
				field.setAccessible(true);
				Column column = field.getAnnotation(Column.class);
				if (column != null) {
					String name = column.name().toUpperCase();
					switch (name) {
					case "ID_":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, StringUtils.uuid());
						}
						break;
					case "PID_":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, GlobalContants.PARENT_ID);
						}
						break;
					case "CREATE_BY":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, ShiroUtils.getUser().getId());
						}
						break;
					case "CREATE_DATE":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, DateTimeUtils.getDate());
						}
						break;
					case "DELETE_FLAG":
						field.set(parameter, "0");
						break;
					}
				}
				field.setAccessible(false);
			}
		} else if (SqlCommandType.UPDATE == sqlCommandType) {
			for (Field field : fields) {
				field.setAccessible(true);
				Column column = field.getAnnotation(Column.class);
				if (column != null) {
					String name = column.name().toUpperCase();
					switch (name) {
					case "PID_":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, GlobalContants.PARENT_ID);
						}
						break;
					case "UPDATE_BY":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, ShiroUtils.getUser().getId());
						}
						break;
					case "UPDATE_DATE":
						if (field.get(parameter) == null || "".equals(field.get(parameter))) {
							field.set(parameter, DateTimeUtils.getDate());
						}
						break;
					}
				}
				field.setAccessible(false);
			}
		}
		return invocation.proceed();
	}

	public Object plugin(Object target) {
		if (target instanceof Executor) {
			return Plugin.wrap(target, this);
		} else {
			return target;
		}
	}

	public void setProperties(Properties properties) {
	}
}